package org.bridgen.runtime.model;

import org.bridgen.runtime.RecoveryHelper;
import org.bridgen.runtime.util.Interval;

/**
 * Default layout end island implementation.
 * 
 * @author Emma Söderberg <emma add cs.lth.se>
 *
 */

public abstract class LayoutEndIsland extends EndIsland {

	/**
	 * Creates a new LayoutEndIsland
	 * @param previous The previous node in the token list
	 * @param interval The corresponding interval
	 * @param value The corresponding value
	 */
	public LayoutEndIsland(LexicalNode previous, Interval interval, String value) {
		super(previous, interval, value);
	}

	/*
	 * (non-Javadoc)
	 * @see org.briplib.recovery.Island#bridgeMatch(org.briplib.recovery.Island, int)
	 */
	@Override
	public boolean bridgeMatch(Island target, int tol) {
		if (isStartIsland(target))  {
			LayoutEndIsland island = (LayoutEndIsland)target;
			return island.indent() != null && 
				island.indent().pos() == indent().pos();
		}
		return false;
	}

	/*
	 * (non-Javadoc)
	 * @see org.briplib.recovery.Island#insertFakeIsland(org.briplib.recovery.Island, org.briplib.recovery.LexicalNode)
	 */
	/*
	@Override
	public void insertFakeIsland(Island island, LexicalNode node) {
		if (island.isFake()) {
			if (isLayoutReef(node)) {
				LayoutReef reef = (LayoutReef)node.getNext().getNextOfType(LayoutReef.class);
				if (reef != indent()) {
					RecoveryHelper.insertBefore(island, reef);
					return;
				}
			}
			RecoveryHelper.insertAfter(island, node);
		}
	}
	*/

	/*
	 * (non-Javadoc)
	 * @see org.briplib.recovery.Island#possibleConstructionSite(org.briplib.recovery.LexicalNode)
	 */
	@Override
	public boolean possibleConstructionSite(LexicalNode node) {
		if (isLayoutReef(node)) {
			LayoutReef reef = (LayoutReef)node;
			if (indent() != null && (reef.pos() <= indent().pos() &&
					reef != indent() && 
					!(isLayoutReef(reef.getNext())))) {
				Island newIsland = constructFakeIsland(node, false);
				RecoveryHelper.insertBefore(newIsland, reef);
				newIsland.buildBridge(this, -1);
				return true;
			}
		}
		else if (isStartIsland(node)) {
			LayoutStartIsland island = (LayoutStartIsland)node;
			if (indent() != null && (!island.hasBridge() && 
					indent().pos() < island.indent().pos())) {
				Island newIsland = constructFakeIsland(node, false);
				RecoveryHelper.insertAfter(newIsland, node);
				newIsland.buildBridge(this, -1);
				return true;
			}
		}
		return false;
	}

	
	/**
	 * Checks if a node is a layout reef
	 * @param node The node to check
	 * @return true if there's a match
	 */
	protected boolean isLayoutReef(LexicalNode node) {
		return node instanceof LayoutReef;
	}
	
	/**
	 * Checks if the given node is a matching start island
	 * @param node The node to check
	 * @return true if it's a matching start island
	 */
	protected boolean isStartIsland(LexicalNode node) {
		return node instanceof LayoutStartIsland;
	}
	
	
	/*
	 * Attribute: LayoutReef LayoutReef.indent
	 */
	private LayoutReef indent;
	public LayoutReef indent() {
		if (indent == null) {
			indent = (LayoutReef)getPreviousOfType(LayoutReef.class);
		}
		return indent;
	}
}
